package gspringboot

import (
	"bytes"
	"gitee.com/hongzhaomin/gspring/iface"
	"gitee.com/hongzhaomin/hzm-common-go/assert"
	"os"
)

func getBanner(environment ConfigurationEnvironment, fallbackBanner Banner) Banner {
	location := defaultBannerLocation
	if environment.ContainsKey(bannerLocationPropName) {
		location = environment.GetStringReplacePlaceholders(bannerLocationPropName)
	}
	if location != "" {
		_, err := os.Stat(location)
		if !os.IsNotExist(err) {
			return textBanner{location: location}
		}
	}
	if fallbackBanner != nil {
		return fallbackBanner
	}
	return gspringBootBanner{}
}

// Banner 接口定义
type Banner interface {
	PrintBanner(environment ConfigurationEnvironment, logger iface.GspringLogger)
}

// ======================= gspringBootBanner ===================
var _ Banner = (*gspringBootBanner)(nil)

type gspringBootBanner struct{}

func (my gspringBootBanner) PrintBanner(_ ConfigurationEnvironment, logger iface.GspringLogger) {
	logger.Println(my.getBanner())
}

func (my gspringBootBanner) getBanner() string {
	banner := []string{
		"",
		"  .         ____          _            __ _ _",
		" /\\\\  __ _ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\",
		"( ( )/ _` |\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
		" \\\\/| (_| | ___)| |_)| | | | | || (_| |  ) ) ) )",
		"  '  \\__, ||____| .__|_| |_|_| |_\\__, | / / / /",
		" ====|___/======|_|==============|___/=/_/_/_/",
	}

	gspringBoot := " :: Gspring Boot :: "

	strapLineSize := 48

	bannerBuf := &bytes.Buffer{}
	for _, line := range banner {
		bannerBuf.WriteString(line)
		bannerBuf.WriteString("\n")
	}

	bannerBuf.WriteString(gspringBoot)

	version := gspringBootVersion
	version = " (v" + version + ")"
	padding := &bytes.Buffer{}
	for padding.Len() < strapLineSize-(len(version)+len(gspringBoot)) {
		padding.WriteString(" ")
	}
	bannerBuf.Write(padding.Bytes())
	bannerBuf.WriteString(version)
	bannerBuf.WriteString("\n")
	return bannerBuf.String()
}

// ======================= textBanner ===================
var _ Banner = (*textBanner)(nil)

type textBanner struct {
	location string
}

func (my textBanner) PrintBanner(environment ConfigurationEnvironment, logger iface.GspringLogger) {
	assert.NotBlank(my.location, "Location must not be null")
	fileContent, err := os.ReadFile(my.location)
	if err != nil {
		panic(err)
	}
	banner := os.Expand(string(fileContent), func(s string) string {
		return environment.GetStringReplacePlaceholders(s)
	})
	logger.Println(banner)
}

// ======================= xormplusBanner ===================
var _ Banner = (*xormplusBanner)(nil)

type xormplusBanner struct{}

func (my xormplusBanner) PrintBanner(_ ConfigurationEnvironment, logger iface.GspringLogger) {
	logger.Println(my.getBanner())
}

func (my xormplusBanner) getBanner() string {
	banner := []string{
		"\\, _ ,_. _ _  _ |    _",
		"/\\(_)|  | | ||_)||_|_\\",
		"             |        ",
	}
	strapLineSize := 22

	bannerBuf := &bytes.Buffer{}
	for _, line := range banner {
		bannerBuf.WriteString(line)
		bannerBuf.WriteString("\n")
	}

	version := xormplusVersion
	version = " (v" + version + ")"
	padding := &bytes.Buffer{}
	for padding.Len() < strapLineSize-(len(version)) {
		padding.WriteString(" ")
	}
	bannerBuf.Write(padding.Bytes())
	bannerBuf.WriteString(version)
	return bannerBuf.String()
}

// ======================= ginplusBanner ===================
var _ Banner = (*ginplusBanner)(nil)

type ginplusBanner struct{}

func (my ginplusBanner) PrintBanner(_ ConfigurationEnvironment, logger iface.GspringLogger) {
	logger.Println(my.getBanner())
}

func (my ginplusBanner) getBanner() string {
	banner := []string{
		" _ . _  _ |    _",
		"(_||| ||_)||_|_\\",
		"._'    |        ",
	}

	strapLineSize := 16

	bannerBuf := &bytes.Buffer{}
	for _, line := range banner {
		bannerBuf.WriteString(line)
		bannerBuf.WriteString("\n")
	}

	version := ginplusVersion
	version = " (v" + version + ")"
	padding := &bytes.Buffer{}
	for padding.Len() < strapLineSize-(len(version)) {
		padding.WriteString(" ")
	}
	bannerBuf.Write(padding.Bytes())
	bannerBuf.WriteString(version)
	return bannerBuf.String()
}
